/*
    双边滤波降噪
    作者：CN.Graphi
*/
Shader "Hidden/CNGraphi/GPostProcess/BilateralFilter"
{

    HLSLINCLUDE
    #include "./Common/GPostProcessFunction.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"

    // 参数
    float _Intensity;
    float _Weight;
    // 结束


    // 双边滤波降噪
    float WeightFactor(float2 uv1, float2 uv2, float weight)
    {
        float3 n1 = normalize( SampleSceneNormals(uv1) );
        float3 n2 = normalize( SampleSceneNormals(uv2) );
        return smoothstep(weight, 1.0, dot(n1, n2));
    }
    float4 BilateralFilter(float2 uv, float2 delta, float weight)
    {
        // 设置双边滤波采样uv
        float2 uv1, uv_1, uv2, uv_2;
        uv1 = uv + delta * 1.3846153846;
        uv_1 = uv - delta * 1.3846153846;
        uv2 = uv + delta * 3.2307692308;
        uv_2 = uv - delta * 3.2307692308;

        // 采样
        float4 t = SampleBlitTex(uv);
        float4 t1 = SampleBlitTex(uv1);
        float4 t_1 = SampleBlitTex(uv_1);
        float4 t2 = SampleBlitTex(uv2);
        float4 t_2 = SampleBlitTex(uv_2);

        // 权重
        float w = 0.2270270270;
        float w_1 = 0.3162162162 * WeightFactor(uv, uv_1, weight);
        float w1 = 0.3162162162 * WeightFactor(uv, uv1, weight);
        float w_2 = 0.0702702703 * WeightFactor(uv, uv_2, weight);
        float w2 = 0.0702702703 * WeightFactor(uv, uv2, weight);

        // 计算最终颜色
        float4 result = t * w;
        result += t_1 * w_1;
        result += t1 * w1;
        result += t_2 * w_2;
        result += t2 * w2;
        result *= rcp(w + w_1 + w1 + w_2 + w2);

        return result;
    }

    half4 FragH (Varyings input) : SV_Target
    {
        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
        return BilateralFilter(input.texcoord, float2(_BlitTexture_TexelSize.x, 0) * _Intensity, _Weight);
    }

    half4 FragV (Varyings input) : SV_Target
    {
        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
        return BilateralFilter(input.texcoord, float2(0, _BlitTexture_TexelSize.y) * _Intensity, _Weight);
    }

    #pragma vertex Vert
    ENDHLSL



    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" }
        Cull Off ZWrite Off

        Pass
        {
            Name "BilateralFilter H"
            HLSLPROGRAM
            #pragma fragment FragH
            ENDHLSL
        }
        Pass
        {
            Name "BilateralFilter V"
            HLSLPROGRAM
            #pragma fragment FragV
            ENDHLSL
        }
    }


    FallBack Off
}